import 'dart:convert';

import 'package:casdon/app/config/env/env_provider.dart';
import 'package:casdon/app_providers.dart';
import 'package:casdon/core/network/i_api_client.dart';
import 'package:casdon/core/utils/json_parse_utils.dart';
import 'package:casdon/modules/device/data/api/ciot_product_category_api.dart';
import 'package:casdon/modules/device/data/api/ciot_product_model_api.dart';
import 'package:casdon/modules/device/data/api/nfc_check_bind_api.dart';
import 'package:casdon/modules/device/data/api/ciot_pairNet_guid_info_api.dart';
import 'package:casdon/modules/device/data/api/auth_login_with_third_user_info_api.dart';
import 'package:casdon/modules/device/data/api/ecology_openness_authenticate_api.dart';
import 'package:casdon/modules/device/data/api/scan_model_api.dart';
import 'package:casdon/modules/device/data/repository/device_repository.dart';

class DeviceRepositoryImpl extends DeviceRepository {
  // 字段类型也是抽象接口
  final IApiClient _apiClient;

  DeviceRepositoryImpl({required IApiClient apiClient})
    : _apiClient = apiClient;

  // 获取ciot 产品类目
  @override
  Future<List<ResponseCiotProductCategoryApi>?> getCiotProductCategory() async {
    final res = await _apiClient
        .getTyped<List<ResponseCiotProductCategoryApi>?>(
          '/client-product/network/getApplianceTypeList',
          fromJsonT: (json) =>
              parseList(json, ResponseCiotProductCategoryApi.fromJson),
        );
    return res?.data;
  }

  // 获取ciot产品对应类目下的产品列表
  @override
  Future<List<ResponseCiotProductModelApi>?> getCiotProductModel({
    required String categoryId,
  }) async {
    final res = await _apiClient.getTyped<List<ResponseCiotProductModelApi>?>(
      '/client-product/network/getProductListById/{id}',
      pathParams: {'id': categoryId},
      fromJsonT: (json) =>
          parseList(json, ResponseCiotProductModelApi.fromJson),
    );
    return res?.data;
  }

  //检查nfc是否已绑定设备
  @override
  Future<ResponseNFCCheckBindApi?> getCheckNfcBind({
    required String virtualId,
    required String pid,
  }) async {
    final res = await _apiClient.getTyped<ResponseNFCCheckBindApi?>(
      '/client-product/nfc/deviceBind/checkBind',
      query: {'pid': pid, 'virtualId': virtualId},
      fromJsonT: (json) =>
          ResponseNFCCheckBindApi.fromJson(json as Map<String, dynamic>),
    );
    return res?.data;
  }

  // 通过设备uuid 解绑nfc
  @override
  Future<Map<String, dynamic>?> delNfcUnBind({required String uuid}) async {
    final res = await _apiClient.delete<Map<String, dynamic>?>(
      '/client-product/nfc/deviceBind/unbind/{uuid}',
      pathParams: {'uuid': uuid},
    );
    return res?["data"];
  }

  // 通过deviceUuid 和virtualId 绑定nfc
  @override
  Future<void> postNfcBind({
    required String deviceUuid,
    required String virtualId,
  }) async {
    await _apiClient.post<void>(
      '/client-product/nfc/deviceBind/bind',
      data: {'deviceUuid': deviceUuid, 'virtualId': virtualId},
    );
    return;
  }

  // 查询用户产品数据《用于在nfc时，在设备离线时进入产品说明页》
  @override
  Future<Map<String, dynamic>> getNFCProductReadMeInfo({
    required String deviceId,
    required String pid,
  }) async {
    final res = await _apiClient.get<Map<String, dynamic>>(
      '/client-product/nfc/user/data/query',
      query: {'pid': pid, 'deviceId': deviceId},
    );
    return res!;
  }

  @override
  Future<List<CiotPairNetGuidInfo>> getCiotPairNetGuid(String pid) async {
    final res = await _apiClient.getTyped<List<CiotPairNetGuidInfo>>(
      '/client-product/network/info/{pid}',
      pathParams: {'pid': pid},
      fromJsonT: (json) => parseList(json, CiotPairNetGuidInfo.fromJson),
    );
    return res?.data ?? const [];
  }

  @override
  Future<AuthLoginWithThirdUserInfoModel?> getAliGenieAuthLogin({
    required String userId,
  }) async {
    final env = getProvider(environmentProvider);
    final res = await _apiClient.postTyped<AuthLoginWithThirdUserInfoModel?>(
      '${env.miffy_url}/v1/aliGenie/authLoginWithThirdUserInfo',
      data: {
        'thirdUserIdentifier': userId,
        'sceneCode': 'casdon_ecology_openness',
        'thirdUserType': 'casdonUser',
      },
      fromJsonT: (json) => AuthLoginWithThirdUserInfoModel.fromJson(
        json as Map<String, dynamic>,
      ),
    );
    return res?.data;
  }

  @override
  Future<EcologyOpennessAuthenticateModel?> ecologyOpennessAuthenticate({
    required String loginStateAccessToken,
  }) async {
    final env = getProvider(environmentProvider);
    final res = await _apiClient.postTyped<EcologyOpennessAuthenticateModel?>(
      '${env.miffy_url}/v1/aliGenie/ecologyOpennessAuthenticate',
      data: {
        'loginStateAccessToken': loginStateAccessToken,
        'encodeType': 'PROJECT_ID',
        'encodeKey': '1379569145504439910',
      },
      fromJsonT: (json) => EcologyOpennessAuthenticateModel.fromJson(
        json as Map<String, dynamic>,
      ),
    );
    return res?.data;
  }

  @override
  Future<EcologyOpennessAuthenticateModel?> authLoginWithAliGenieUserInfo({
    required String loginStateAccessToken,
    required String sessionId,
  }) async {
    final env = getProvider(environmentProvider);
    final res = await _apiClient.postTyped<EcologyOpennessAuthenticateModel?>(
      '${env.miffy_url}/v1/aliGenie/authLoginWithAliGenieUserInfo',
      data: {
        'encryptedAligenieUserIdentifier': loginStateAccessToken,
        'sessionId': sessionId,
      },
      fromJsonT: (json) => EcologyOpennessAuthenticateModel.fromJson(
        json as Map<String, dynamic>,
      ),
    );
    return res?.data;
  }

  @override
  Future<EcologyOpennessAuthenticateModel?> authLoginWithTaoBaoUserInfo({
    required String loginStateAccessToken,
    required String sessionId,
  }) async {
    final env = getProvider(environmentProvider);
    final res = await _apiClient.postTyped<EcologyOpennessAuthenticateModel?>(
      '${env.miffy_url}/v1/aliGenie/authLoginWithTaoBaoUserInfo',
      data: {
        'encryptedTaobaoUserIdentifier': loginStateAccessToken,
        'sessionId': sessionId,
      },
      fromJsonT: (json) => EcologyOpennessAuthenticateModel.fromJson(
        json as Map<String, dynamic>,
      ),
    );
    return res?.data;
  }

  @override
  Future<void> bindDeviceWithThirdUserInfo({
    required String clientId,
    required String code,
  }) async {
    final env = getProvider(environmentProvider);
    await _apiClient.post<void>(
      '${env.miffy_url}/v1/aliGenie/bindDeviceWithThirdUserInfo',
      data: {'clientId': clientId, 'code': code},
    );
    return;
  }

  @override
  Future<Map<String, dynamic>?> sendTMBindVerifyCode({
    required String sessionId,
    required String phoneNumber,
  }) async {
    final env = getProvider(environmentProvider);
    final res = await _apiClient.postTyped<Map<String, dynamic>>(
      '${env.miffy_url}/v1/aliGenie/ecologyOpennessSendVerificationCode',
      data: {
        'sessionId': sessionId,
        'phoneNumber': phoneNumber,
        'region': '+86',
      },
      fromJsonT: (json) =>
          Map<String, dynamic>.from(json as Map<String, dynamic>),
    );
    return res?.data;
  }

  @override
  Future<Map<String, dynamic>?> findTMUserListToAuthLoginWithPhoneNumber({
    required String code,
    required String phoneNumber,
    required String sessionId,
  }) async {
    final env = getProvider(environmentProvider);
    final res = await _apiClient.postTyped<Map<String, dynamic>>(
      '${env.miffy_url}/v1/aliGenie/findUserListToAuthLoginWithPhoneNumber',
      data: {
        'sessionId': sessionId,
        'phoneNumber': phoneNumber,
        'code': code,
        'region': '+86',
      },
      fromJsonT: (json) =>
          Map<String, dynamic>.from(json as Map<String, dynamic>),
    );
    return res?.data;
  }

  @override
  Future<ScanModel?> scanCodeBind({
    required String userOpenId,
    required String clientId,
    required String code,
  }) async {
    final env = getProvider(environmentProvider);
    final res = await _apiClient.postTyped<ScanModel?>(
      '${env.miffy_url}/v1/aliGenie/scanCodeBind',
      data: {
        'id': userOpenId,
        'encodeType': 'PROJECT_ID',
        'encodeKey': '1379569145504439910',
        'idType': 'OPEN_ID',
        'code': code,
        'clientId': clientId,
      },
      fromJsonT: (json) => ScanModel.fromJson(json as Map<String, dynamic>),
    );
    return res?.data;
  }
}
